package com.ljx.comprehensiveCase.framework.context.support;

import com.ljx.comprehensiveCase.framework.beans.BeanDefinition;
import com.ljx.comprehensiveCase.framework.beans.MultiplePropertyValues;
import com.ljx.comprehensiveCase.framework.beans.PropertyValue;
import com.ljx.comprehensiveCase.framework.beans.factory.support.BeanDefinitionRegistry;
import com.ljx.comprehensiveCase.framework.beans.factory.xml.XmlBeanDefinitionReader;
import com.ljx.comprehensiveCase.framework.utils.StringUtils;

import java.lang.reflect.Method;

/**
 *
 * 该类主要是加载类路径下的配置文件，并进行bean对象的创建，主要完成以下功能：
 *
 * @ 在构造方法中，创建BeanDefinitionReader对象。
 * @ 在构造方法中，调用refresh()方法，用于进行配置文件加载、创建bean对象并存储到容器中。
 * @ 重写父接口中的getBean()方法，并实现依赖注入操
 *
 * @作者 LJX
 * @日期 2022/12/28 9:50
 */
public class ClassPathXmlApplicationContext extends AbstractApplicationContext{

    public ClassPathXmlApplicationContext(String configLocation) {
        this.configLocation = configLocation;
        //构建XmlBeanDefinitionReader对象
        beanDefinitionReader = new XmlBeanDefinitionReader();
        try {
            refresh();
        } catch (Exception e) {
        }
    }

    /**
     * 根据bean的id属性值获取bean对象
     * @param name
     * @return
     * @throws Exception
     */
    @Override
    public Object getBean(String name) throws Exception {

        Object o = singletonObjects.get(name);
        if(null != o){
            return o;
        }

        //获取注册器
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        BeanDefinition beanDefinition = registry.getBeanDefinition(name);
        if(null == beanDefinition){
            return null;
        }

        //获取类名并通过反射创建对象
        String className = beanDefinition.getClassName();
        Class<?> aClass = Class.forName(className);
        Object beanObj = aClass.getDeclaredConstructor().newInstance();

        //获取类属性
        MultiplePropertyValues multiplePropertyValues = beanDefinition.getMultiplePropertyValues();
        for (PropertyValue pv : multiplePropertyValues) {
            String pvname = pv.getName();
            String value = pv.getValue();
            String ref = pv.getRef();
            String methodName = StringUtils.splicingSetMethod(pvname);
            //ref和value处理方式不一样
            if(null != ref && !"".equals(ref)){
                //ref需要依赖注入
                Object bean = getBean(ref);
                //调用set方法注入
//                Method method = aClass.getMethod(methodName);
//                method.invoke(beanObj, bean);
                Method[] methods = aClass.getMethods();
                for (Method method : methods) {
                    if(methodName.equals(method.getName())) {
                        method.invoke(beanObj,bean);
                    }
                }

            }

            if(null != value && !"".equals(value)){
                //value需要赋值
                Method method = aClass.getMethod(methodName, String.class);
                method.invoke(beanObj, value);
            }

        }

        //返回前 将对象放入容器
        singletonObjects.put(name, beanObj);

        return beanObj;
    }

    @Override
    public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {

        Object bean = getBean(name);
        if(null == bean){
            return null;
        }
        //对象类型转换
        return clazz.cast(bean);
    }
}
